package com.tools.cleanmaster.functionpage;

import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Point;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Shader;
import android.support.v4.content.ContextCompat;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.LinearInterpolator;

import com.tools.cleanmaster.R;
import com.tools.cleanmaster.utils.UiUtils;

import java.text.SimpleDateFormat;
import java.util.Random;

public class CpuTempCurveView extends View {
    private int width;
    private int height;

    //网格线条数
    private int gridLineCount = 4;
    //网格线条竖直间距
    private int gridVerticalDistance;
    //网格线画笔
    private Paint mGridPaint;

    //温度相关：
    //最高温度
    private int mHighestTemp = 50;
    //网格温度间距值
    private int mTempInterval = 10;
    //温度Text左边线右边距
    private int mTempMaginRight = 35;
    //温度数字画笔
    private Paint mTempPaint;
    //文字的高度
    private int mTitleHeight;

    //时间刻度相关：
    //刻度线个数，间距计算+2
    private int mTimeCount = 10;
    //刻度间距
    private int mTimeDistance;
    //时间间距、默认15分钟
    private long mTimeInterval = 15 * 1000 * 60;
    //刻度画笔
    private Paint mTimeMarkPaint;
    //时间点画笔
    private Paint mTimePaint;
    //起始时间
    private long mCurrentTime = System.currentTimeMillis();

    //title提示相关
    //title距离左边距离
    private int mTitleMarginLeft = 15;
    private Paint mTitlePaint;

    //温度折线相关
    private Path mTempPath;
    private Paint mTempPathPaint;
    private Paint mTempPaintPoint;
    LinearGradient lg;
    private Point[] mPoints;

    int mOffset;
    private Paint mCirclePaint;
    Context mContext;
    private int halfWhite;
    //终点小圆圈
    private Paint minCirclePaint;
    private int mCurrentTemp = 30;
    private boolean isOndrawCurve = false;
    private int stressColor;
    private int curveLineColor;
    Bitmap result;
    Bitmap markResult;

    public CpuTempCurveView(Context context) {
        super(context);
    }

    public CpuTempCurveView(Context context, AttributeSet attrs) {
        super(context, attrs);
        mContext = context;
        stressColor = ContextCompat.getColor(mContext, R.color.cpu_temp_curve_color);
        curveLineColor = ContextCompat.getColor(mContext, R.color.cpu_temp_curve_line_color);

        halfWhite = ContextCompat.getColor(mContext, R.color.common_half_white);
        mTitleMarginLeft = UiUtils.dipToPx(context, 10);
        mTempMaginRight = UiUtils.dipToPx(context, 25);
        //初始化网格线画笔
        mGridPaint = new Paint();
        mGridPaint.setAntiAlias(true);
        mGridPaint.setStrokeWidth(1);
        mGridPaint.setStyle(Paint.Style.FILL_AND_STROKE);
        mGridPaint.setColor(ContextCompat.getColor(mContext, R.color.cpucool_gride_line));

        //初始化温度画笔
        mTempPaint = new Paint();
        mTempPaint.setAntiAlias(true);
        mTempPaint.setStrokeWidth(1);
        mTempPaint.setStyle(Paint.Style.FILL_AND_STROKE);
        mTempPaint.setColor(halfWhite);

        //初始化刻度线画笔
        mTimeMarkPaint = new Paint();
        mTimeMarkPaint.setAntiAlias(true);
        mTimeMarkPaint.setStrokeWidth(1);
        mTimeMarkPaint.setStyle(Paint.Style.FILL_AND_STROKE);
        mTimeMarkPaint.setColor(halfWhite);

        //初始化时间点画笔
        mTimePaint = new Paint();
        mTimePaint.setAntiAlias(true);
        mTimePaint.setStrokeWidth(0.5f);
        mTimePaint.setTextSize(UiUtils.dipToPx(mContext, 8));
        mTimePaint.setStyle(Paint.Style.FILL_AND_STROKE);
        mTimePaint.setColor(halfWhite);

        //初始化Title画笔
        mTitlePaint = new Paint();
        mTitlePaint.setAntiAlias(true);
        mTitlePaint.setStrokeWidth(1);
        mTitlePaint.setStyle(Paint.Style.FILL_AND_STROKE);
        mTitlePaint.setColor(halfWhite);

        //初始化温度折线相关
        mTempPath = new Path();
        mTempPathPaint = new Paint();
        mTempPathPaint.setAntiAlias(true);
        mTempPathPaint.setColor(Color.BLUE);
        mTempPathPaint.setStyle(Paint.Style.FILL);

        //温度曲线
        mTempPaintPoint = new Paint();
        mTempPaintPoint.setAntiAlias(true);
        mTempPaintPoint.setStrokeWidth(UiUtils.dip2px(mContext, 3));
        mTempPaintPoint.setStyle(Paint.Style.STROKE);

        mCirclePaint = new Paint();
        mCirclePaint.setColor(ContextCompat.getColor(context, R.color.common_black_color));
        mCirclePaint.setAntiAlias(true);
        mCirclePaint.setStyle(Paint.Style.FILL);
        mCirclePaint.setFilterBitmap(true);

        minCirclePaint = new Paint();
        minCirclePaint.setAntiAlias(true);
        minCirclePaint.setColor(halfWhite);
        minCirclePaint.setStrokeWidth(UiUtils.dipToPx(context, 3));
        minCirclePaint.setStyle(Paint.Style.FILL);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        onDrawGridLineView(canvas);
        onDrawTempTextView(canvas);
        onDrawTitleView(canvas);
        if (isOndrawCurve) {
            canvas.drawBitmap(createCircle(), 0, 0, null);
        }
        onDrawTimeTextView(canvas);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        height = h;
        width = w;
        mTitleHeight = UiUtils.dipToPx(60);
        int minHeight = (h - mTitleHeight) / (gridLineCount * 2 - 1);
        gridVerticalDistance = minHeight * 2;
        mTimeDistance = w / (mTimeCount + 2);
    }

    private void onDrawTempTextView(Canvas canvas) {
        mTempPaint.setTextSize(UiUtils.dipToPx(mContext, 8));
        canvas.drawText("(Unit ℃)",
                width - mTempMaginRight - (mTempPaint.measureText("10") + mTempPaint.measureText("(Unit ℃)")) / 2,
                mTitleHeight - UiUtils.dipToPx(mContext, 30), mTempPaint);
        mTempPaint.setTextSize(UiUtils.dipToPx(mContext, 8));
        for (int i = 0; i < gridLineCount; i++) {
            canvas.drawText("" + (mHighestTemp - i * mTempInterval), width - mTempMaginRight, mTitleHeight + i * gridVerticalDistance, mTempPaint);
        }
    }

    private void onDrawTimeTextView(Canvas canvas) {
        for (int i = 1; i <= mTimeCount; i++) {
            if (i > mTimeCount - 1) {
                break;
            }
            if (i % 2 == 1) {
                String currentTime = getHourAndMinute(mCurrentTime - (mTimeCount - i) / 2 * mTimeInterval);
                canvas.drawText(currentTime, i * mTimeDistance - mTimePaint.measureText(currentTime) / 2, mTitleHeight + (gridLineCount - 1) * gridVerticalDistance, mTimePaint);
            }
        }
    }

    private void onDrawGridLineView(Canvas canvas) {
        int count = gridLineCount;
        for (int i = 0; i < count; i++) {
            int y = mTitleHeight + i * gridVerticalDistance;
            canvas.drawLine(0, y, width, y, mGridPaint);
        }

        int lineCount = mTimeCount + 2;
        for (int i = 1; i <= lineCount; i++) {
            if (i > lineCount - 1) {
                break;
            }

            if (i % 2 == 1) {
                int x = i * mTimeDistance;
                canvas.drawLine(x,
                        mTitleHeight,
                        x,
                        height,
                        mGridPaint
                );
            }
        }
    }

    private void onDrawTitleView(Canvas canvas) {
        mTitlePaint.setTextSize(UiUtils.spToPx(37));
        mTitlePaint.setFakeBoldText(true);
        mTitlePaint.setColor(Color.WHITE);

        //计算出文字的高度
        Paint.FontMetrics metrics = mTitlePaint.getFontMetrics();
        float baseline = metrics.bottom - metrics.top;

        canvas.drawText(mCurrentTemp + "", mTitleMarginLeft, baseline / 2 + 20, mTitlePaint);

        float marginRight = mTitlePaint.measureText(mCurrentTemp + "") + 5;
        mTitlePaint.setTextSize(UiUtils.spToPx(8));
        mTitlePaint.setColor(halfWhite);
        mTitlePaint.setFakeBoldText(false);
        canvas.drawText("℃ " + mContext.getString(R.string.function_cpucool_overtext), mTitleMarginLeft + marginRight,
                baseline / 2 + 20, mTitlePaint);
    }

    private String getHourAndMinute(long timeStamp) {
        SimpleDateFormat format = new SimpleDateFormat("HH:mm");
        return format.format(timeStamp);
    }

    private void onDrawTempBrokenLine(Canvas canvas) {
        Point startp;
        Point endp;
        Path mmPath = new Path();
        mTempPath.reset();
        mTempPath.moveTo(mPoints[0].x, mPoints[0].y);
        mmPath.moveTo(mPoints[0].x, mPoints[0].y);
        for (int i = 0; i < mPoints.length - 1; i++) {
            startp = mPoints[i];
            endp = mPoints[i + 1];
            int wt = (startp.x + endp.x) / 2;
            Point p3 = new Point();
            Point p4 = new Point();
            p3.y = startp.y;
            p3.x = wt;
            p4.y = endp.y;
            p4.x = wt;
            mTempPath.cubicTo(p3.x, p3.y, p4.x, p4.y, endp.x, endp.y);
            mmPath.cubicTo(p3.x, p3.y, p4.x, p4.y, endp.x, endp.y);
        }

        mTempPath.lineTo(mTimeDistance * (mTimeCount - 1), height);
        mTempPath.lineTo(0, height);
        mTempPath.close();
        if (lg == null) {
            lg = new LinearGradient(
                    0,
                    gridVerticalDistance,
                    width,
                    height,
                    new int[]{
                            ContextCompat.getColor(mContext, R.color.cpu_temp_curve_start),
                            ContextCompat.getColor(mContext, R.color.cpu_temp_curve_end),
                            Color.TRANSPARENT
                    },
                    new float[]{
                            0.0f, 0.7f, 1.0f
                    },
                    Shader.TileMode.CLAMP
            );
        }
        mTempPathPaint.setShader(lg);
        canvas.drawPath(mTempPath, mTempPathPaint);

        mTempPaintPoint.setColor(curveLineColor);
        canvas.drawPath(mmPath, mTempPaintPoint);

        minCirclePaint.setColor(Color.WHITE);
        canvas.drawCircle(mPoints[mPoints.length - 1].x, mPoints[mPoints.length - 1].y,
                UiUtils.dipToPx(mContext, 8), minCirclePaint);
        minCirclePaint.setColor(stressColor);
        canvas.drawCircle(mPoints[mPoints.length - 1].x, mPoints[mPoints.length - 1].y,
                UiUtils.dipToPx(mContext, 6), minCirclePaint);
    }

    private Bitmap createCircle() {
        if (result == null) {
            result = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        }
        result.eraseColor(Color.argb(0, 0, 0, 0));
        Canvas mCanvas = new Canvas(result);
        mCirclePaint.setXfermode(null);
        mCanvas.drawRect(0, 0, mOffset, height, mCirclePaint);
        mCirclePaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));

        mCanvas.drawBitmap(createMarkBitmap(), 0, 0, mCirclePaint);
        return result;
    }

    private Bitmap createMarkBitmap() {
        if (markResult == null) {
            markResult = Bitmap.createBitmap(width, width, Bitmap.Config.ARGB_8888);
        }
        markResult.eraseColor(Color.argb(0, 0, 0, 0));
        Canvas mCanvas = new Canvas(markResult);
        onDrawTempBrokenLine(mCanvas);
        return markResult;
    }

    private void startCpuTempCurveAnimation() {
        isOndrawCurve = true;
        ValueAnimator animator = ValueAnimator.ofInt(0, width);
        animator.setDuration(2000);
        animator.setInterpolator(new LinearInterpolator());
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                mOffset = (Integer) animation.getAnimatedValue();
                postInvalidate();
            }
        });
        animator.start();
    }

    public void setCurrentTemp(int temp) {
        if (temp > 50) {
            temp = 48;
        } else if (temp < 30) {
            temp = 30;
        }
        this.mCurrentTemp = temp;
        int he = (gridLineCount + 2) * gridVerticalDistance;
        Random random = new Random();
        mPoints = new Point[(mTimeCount + 3) / 2];
        for (int i = 0; i < mPoints.length; i++) {
            if (i == 0) {
                mPoints[i] = new Point(0, he - (random.nextInt(15) + 30) * gridVerticalDistance / 10);
            } else if (i == 1) {
                mPoints[i] = new Point(mTimeDistance, he - (random.nextInt(15) + 30) * gridVerticalDistance / 10);
            } else if (i == mPoints.length - 1) {
                mPoints[i] = new Point((2 * i - 1) * mTimeDistance,
                        he - temp * gridVerticalDistance / 10);
            } else {
                mPoints[i] = new Point((2 * i - 1) * mTimeDistance,
                        he - (random.nextInt(15) + 30) * gridVerticalDistance / 10);
            }
        }
        startCpuTempCurveAnimation();
    }
}
